package com.vlong.town.util.config.database;

import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.github.pagehelper.PageInterceptor;
import com.vlong.town.util.interceptor.SqlPrintInterceptor;

@Configuration
@AutoConfigureAfter(DataSourceConfig.class)
@EnableTransactionManagement
public class MybatisConfiguration {

    // 日志记录
    private Log logger = LogFactory.getLog(MybatisConfiguration.class);

    @Value("${mybatis.typeAliasesPackage}")
    private String typeAliasesPackage;// 配置实体类型别名

    @Value("${mybatis.mapperLocations}")
    private String mapperLocations;// 配置mapper xml文件路径

    @Value("${mybatis.configLocation}")
    private String configLocation;// 配置全局配置文件

    @Autowired
    private DataSource dataSource;// 数据源

    /**
     * SqlSessionFactory
     * @return SqlSessionFactory
     */
    @Bean(name = "sqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory() {
        try {
            // 设置配置项
            SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
            sessionFactoryBean.setDataSource(this.dataSource);
            sessionFactoryBean.setTypeAliasesPackage(this.typeAliasesPackage);
            Resource[] resources = new PathMatchingResourcePatternResolver().getResources(this.mapperLocations);
            sessionFactoryBean.setMapperLocations(resources);
            sessionFactoryBean.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
            // 分页插件&SQL语句拦截插件
            Interceptor[] plugins = new Interceptor[]{pageHelper(), sqlPrintInterceptor()};
//            Interceptor[] plugins = new Interceptor[]{pageHelper()};
            sessionFactoryBean.setPlugins(plugins);
            return sessionFactoryBean.getObject();
        } catch (IOException e) {
            logger.error("MyBatis Resolver Mapper * Xml Error", e);
            return null;
        } catch (Exception e) {
            logger.error("Mybatis SqlSessionFactoryBean Create Error", e);
            return null;
        }
    }

    /**
     * SqlSessionTemplate
     * @param sqlSessionFactory
     * @return SqlSessionTemplate
     */
    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    /**
     * 事务管理
     * @return PlatformTransactionManager
     */
    @Bean
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * 将要执行的sql进行日志打印（不想拦截，就把这方法注释掉）
     * @return SqlPrintInterceptor
     */
    @Bean
    public SqlPrintInterceptor sqlPrintInterceptor() {
        return new SqlPrintInterceptor();
    }

    /**
     * 分页插件
     * @return PageHelper
     */
    @Bean
    public PageInterceptor pageHelper() {
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("offsetAsPageNum", "true");
        properties.setProperty("rowBoundsWithCount", "true");
        properties.setProperty("pageSizeZero", "true");
        properties.setProperty("reasonable", "false");
        properties.setProperty("supportMethodsArguments", "false");
        properties.setProperty("returnPageInfo", "check");
        properties.setProperty("params", "pageNum=pageHelperStart;pageSize=pageHelperRows;");
        pageInterceptor.setProperties(properties);
        return pageInterceptor;
    }
}
